home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / UTIL / ES 1.2 Package.sit / ES 1.2 Package / Developer’s toolkit / ESDemo.c 1.1.1 ƒ / ESDemo.c next >
C/C++ Source or Header  |  1995-12-09  |  25KB  |  757 lines

  1. /* ---------------------------------------------------------------------------
  2. ESDemo.c
  3.     
  4.     ゥ1995 Ammon Skidmore, Skidperfect Software Inc.  All Rights Reserved.
  5.     
  6.     Freeware: use and borrow whatever code you want for your own modules.
  7.     
  8.     This is a "quick" hack that I threw together to test and demonstrate
  9.     Extensions Strip's powerful additions to the Control Strip API.  Do not
  10.     think that I bothered to optimize anything or that I choose the best methods
  11.     to approach each situation.  I'd rather waste my time doing that to ES :-)
  12.     
  13.     Key features of this module:
  14.     -    Fat binary.
  15.     -    Backward compatibility with Control/Desktop Strip.
  16.     -    Intelligent drag handling.  Under Control/Desktop Strip the draggable
  17.         area is the location of the module's icon.  Under Extensions Strip this
  18.         area is the total amount of space that the module takes up.
  19.     -    2 out of the 3 possible methods for sending "safe" AppleEvents that don't rely
  20.         upon the front process' context.  Under Control/Desktop Strip the event is still
  21.         sent, but will not work if the front process does not support Apple Events.
  22.     -    Ability to get key presses under Extensions Strip without having to install
  23.         a custom jGNE filter (as my Key Holder module does.)
  24.     -    Ability to change the sdevFeatures without having to restart.  Examples are
  25.         given for changing almost all of the possible features, even locking and
  26.         unlocking my sdev code.
  27.     -    Demonstrates the changing of display height and width.
  28.     
  29.     How to build the FAT module:
  30.     -    Compile the 68K project first.  It will create a clean module (code + what's
  31.         in the resource file "ESDemo.オ.rsrc") because the "Merge To File" option is OFF.
  32.     -    Compile the PPC project last.  It will append its code to the module because
  33.         the "Merge To File" option is ON.  Note that you will have to change the
  34.         access paths to allow the project to find the "ExtensionsStripLib" shared library.
  35.     
  36.     Other notes:
  37.     -    For PPC compiling, remember to use 'weak links' to shared libraries that may not
  38.         be on every user's computer.  Not doing so will cause a crash because Extensions
  39.         Strip will be forced to quit if the library is not present.  Modules should use
  40.         Gestalt calls to determine the presence of libraries they use.
  41.         For example, this project has a weak link to the DragLib, yet it does not have
  42.         one to the ExtensionsStripLib or the InterfaceLib because these two libraries
  43.         will always be present (PPC ES will not load without the ExtensionsStripLib.)
  44.     
  45. Version History
  46. -=-=-=-=-=-=-=-
  47. 1.0        8/95 - 10/95    - by Ammon Skidmore
  48.         30 Oct, 1995    - Made THINK compiler friendly by Vincent Tan.
  49.  
  50. 1.1        9 Nov, 1995        - Added the menu item 'Large Icon' to demonstrate the changing
  51.                         of display height and width.  Also, the icons were slightly
  52.                         modified, the creator type was changed to '!!!!', and a
  53.                         'hfdr' resource was added so programs like Conflict Catcher
  54.                         can look at our info text.  Maybe future Finders will display
  55.                         this balloon help as well...
  56.         15 Nov, 1995    - Added Code Warrior 7 projects, by Fran腔is Pottier.
  57.  
  58. 1.1.1    20 Nov, 1995    - Fixed a bug that caused the icon to be drawn incorrectly
  59.                         when not using Extensions Strip.
  60.                         - Changed the drag handlers to return dragNotAcceptedErr when
  61.                         the draw was not accepted, instead of the value -1 as before.
  62. -=-=-=-=-=-=-=-
  63. Framework taken from the CSShell.c Control Strip Sample by Martin R. Wachter.
  64. It is freely availible and can be found on the usual UMich/Info-Mac mirrors.
  65. --------------------------------------------------------------------------- */
  66.  
  67. #ifdef powerc
  68.     // for Metrowerks' linker, this defines the mixed-mode interface for main().
  69.     ProcInfoType __procinfo = kPascalStackBased
  70.          | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  71.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  72.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
  73.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Rect*)))
  74.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(WindowRef)));
  75. #endif
  76.  
  77. #include "ESDemo.h"
  78.  
  79. #ifndef __GESTALT__
  80.     #include <Gestalt.h>
  81. #endif  __GESTALT__
  82.  
  83. #ifndef    FALSE
  84.     #define    FALSE    false
  85. #endif
  86.  
  87. #ifndef    TRUE
  88.     #define    TRUE    true
  89. #endif
  90.  
  91. /******************************************************************************
  92.  main: Control Strip's entry point into our sdev code
  93.  ******************************************************************************/
  94. pascal long main (long message, long params, Rect *statusRect, WindowRef statusPort)
  95. {
  96.     register long        result = 0L;
  97.     
  98.     switch (message)
  99.     {
  100.         //
  101.         // Default Control Strip selectors:
  102.         //
  103.         
  104.         case sdevInitModule:         // check environs, allocate globals
  105.             result = sdevInit(statusPort);
  106.             break;
  107.         
  108.         case sdevCloseModule:         // release my memory
  109.             sdevClose((MyGlobalHandle) params, statusPort);
  110.             break;
  111.         
  112.         case sdevFeatures:             // let the strip track the mouse down
  113.             result = (**(MyGlobalHandle) params).currentFeatures;
  114.             break;
  115.         
  116.         case sdevGetDisplayWidth:    // inform the strip how much space we need
  117.             result = kTriangleWidth;
  118.             if ((**(MyGlobalHandle) params).useLargeIcon)
  119.                 result += kLargeIconWidth + ((unsigned long)kLargeIconWidth << 16);
  120.             else
  121.                 result += kSmallIconWidth;
  122.             break;
  123.         
  124.         case sdevPeriodicTickle:    // never called by Extensions Strip because we
  125.         {                            // returned the sdevDontPeriodicTickle bit.
  126.             Rect    viewRect = *statusRect;
  127.             
  128.             // update the draggable box upon each idle cycle in case the user
  129.             // shrunk the Control Strip bar so that we are not visible, but our
  130.             // old position still is because the end of the bar is there.
  131.             viewRect.right -= kTriangleWidth;
  132.             (**(MyGlobalHandle) params).myBox = viewRect;
  133.             
  134.             break;
  135.         }
  136.         
  137.         case sdevDrawStatus:         // draw my icon and arrow pict
  138.             sdevDraw((MyGlobalHandle) params, statusRect, statusPort);
  139.             break;
  140.         
  141.         case sdevMouseClick:         // the mouse was clicked & released in my button
  142.             result = sdevClick((MyGlobalHandle) params, statusRect, statusPort);
  143.             break;
  144.         
  145.         case sdevSaveSettings:        // no settings in this module
  146.             break;
  147.         
  148.         case sdevShowBalloonHelp:    // we have a custom ballon help string
  149.         {
  150.             Str255    helpString;
  151.             
  152.             SBGetDetachedIndString(helpString, (**(MyGlobalHandle) params).myStrings, kHelpStringIndex);
  153.             SBShowHelpString(statusRect, helpString);
  154.             
  155.             break;
  156.         }
  157.         
  158.         //
  159.         // Extensions Strip specific selectors:
  160.         // Note that we check for the presence of ES just in case...
  161.         //
  162.         
  163.         case sdevInAppContext:        // we are inside Extensions Strip's context so
  164.                                     // is is safe to send Apple Events from here.
  165.         {
  166.             ProcessSerialNumber    finderPSN;
  167.             ProcessInfoRec        infoRec;
  168. #define        kFinderType            'FNDR'
  169. #define        kSysCreator            'MACS'
  170.  
  171.             if ((**(MyGlobalHandle) params).hasExtensionsStrip) {
  172.                 infoRec.processInfoLength    =    sizeof(ProcessInfoRec);
  173.                 infoRec.processName            =    nil;    //    no name wanted processName;
  174.                 infoRec.processAppSpec        =    nil;    //    no spec wanted &procSpec;
  175.                 
  176.                 if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
  177.                     QuitProcess(finderPSN, FALSE);    // FALSE because we don't HAVE to use
  178.                                                     // _SBSimpleAESend here
  179.             }
  180.             break;
  181.         }
  182.         
  183.         case sdevInterceptedEvent:    // a chance to look at and modify the current event
  184.         {
  185.             EventRecord    *theEvent;
  186.             
  187.             if ((**(MyGlobalHandle) params).hasExtensionsStrip) {
  188.                 // for demonstration's purpose, we'll intercept command + *
  189.                 // (* on the keypad only since cmd-shift-8 is an FKEY combo that
  190.                 // is intercepted by the System.)
  191.                 theEvent = SBGetCurrentEvent();
  192.             // we can assume a keydown since our mask filters out the rest.
  193.             //    if (theEvent->what == keyDown)
  194.                     if (theEvent->modifiers & cmdKey) {
  195.                         switch (theEvent->message & charCodeMask)
  196.                         {
  197.                             case '*':
  198.                                 SysBeep(0);
  199.                                 theEvent->what = nullEvent;        // don't pass on the event
  200.                                 break;
  201.                             default:
  202.                                 break;
  203.                         }
  204.                     }
  205.             }
  206.             break;
  207.         }
  208.         
  209.         case sdevDragAccept:    // let Extensions Strip know if we won't handle the drag
  210.             if ((**(MyGlobalHandle) params).hasExtensionsStrip &&
  211.                         !(**(MyGlobalHandle) params).canAcceptDrag)
  212.                 result = 1;                // we don't accept the drag
  213.             break;
  214.         
  215.         case sdevEventMask:        // let Extensions Strip know we want key down events
  216.             if ((**(MyGlobalHandle) params).hasExtensionsStrip)
  217.                 result = keyDownMask;    // our GNE style event mask
  218.             break;
  219.     }
  220.     
  221.     return (result);
  222. }
  223.  
  224. /******************************************************************************
  225.  sdevClick: handle a click in our status rect
  226.  ******************************************************************************/
  227. long sdevClick(MyGlobalHandle globH, const Rect    *statusRect, WindowRef statusPort)
  228. {
  229.     short            menuID;
  230.     MenuHandle        menuH = (**globH).myMenuH;    // local copy to save deferencing
  231.     long            result = 0L;
  232.     char            itemMark;
  233.     short            theBit;
  234.     
  235.     // reflect the current features in th popup menu
  236.     itemMark = ((**globH).currentFeatures & (1L<<sdevWantMouseClicks)) ? sdevMenuItemMark : noMark;
  237.     SetItemMark(menuH, kHiliteClicks, itemMark);
  238.     itemMark = ((**globH).currentFeatures & (1L<<sdevHasCustomHelp)) ? sdevMenuItemMark : noMark;
  239.     SetItemMark(menuH, kCustomBalloons, itemMark);
  240.     itemMark = ((**globH).currentFeatures & (1L<<sdevInterceptAllEvents)) ? sdevMenuItemMark : noMark;
  241.     SetItemMark(menuH, kCheckKeyDowns, itemMark);
  242.     itemMark = ((**globH).useLargeIcon) ? sdevMenuItemMark : noMark;
  243.     SetItemMark(menuH, kUseLargeIcon, itemMark);
  244.     itemMark = ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) ? sdevMenuItemMark : noMark;
  245.     SetItemMark(menuH, kUseDragNDrop, itemMark);
  246.     
  247.     // disable what COntrol/Desktop Strip doesn't support
  248.     if (!(**globH).hasExtensionsStrip) {
  249.         DisableItem(menuH, kSafeFinderQuit2);
  250.         SetItemMark(menuH, kCheckKeyDowns, noMark);
  251.     }
  252.     
  253.     // show our popup menu
  254.     menuID = SBTrackPopupMenu(statusRect, menuH);
  255.     
  256.     switch (menuID){
  257.         
  258.         case kBeepIfPPC:
  259. #ifdef powerc
  260.             SysBeep(0);
  261. #endif
  262.             break;
  263.         
  264.         case kHiliteClicks:
  265.             theBit = sdevWantMouseClicks;
  266.             // pass on
  267.         
  268.         case kCustomBalloons:
  269.             if (menuID == kCustomBalloons)
  270.                 theBit = sdevHasCustomHelp;
  271.             // pass on
  272.         
  273.         case kCheckKeyDowns:
  274.             if (menuID == kCheckKeyDowns)
  275.                 theBit = sdevInterceptAllEvents;
  276.             // pass on
  277.         
  278.         case kUseDragNDrop:
  279.             if ((**globH).hasExtensionsStrip) {
  280.                 if (menuID == kUseDragNDrop) {
  281.                     theBit = sdevHasDragHandlers;
  282.                     // Install/remove handlers for fun.  We can also now
  283.                     // unlock our code, all for demonstration purposes.
  284.                     if ((**globH).currentFeatures & (1L<<sdevHasDragHandlers)) {
  285.                         (**globH).currentFeatures -= (1L<<sdevKeepModuleLocked);
  286.                         RemoveDragHandlers(statusPort, globH);
  287.                         DisableItem(menuH, kDragFiles);
  288.                         DisableItem(menuH, kDragTextClippings);
  289.                     } else {
  290.                         (**globH).currentFeatures += (1L<<sdevKeepModuleLocked);
  291.                         InstallDragHandlers(statusPort, globH);
  292.                         EnableItem(menuH, kDragFiles);
  293.                         EnableItem(menuH, kDragTextClippings);
  294.                     }
  295.                 }
  296.                 
  297.                 // handle the passed bit
  298.                     if ((**globH).currentFeatures & (1L<<theBit))
  299.                         (**globH).currentFeatures -= (1L<<theBit);
  300.                     else
  301.                         (**globH).currentFeatures += (1L<<theBit);
  302.                     result = (1L<<sdevFeaturesChange);    // request a sdevFeatures call
  303.             }
  304.             break;
  305.         
  306.         case kUseLargeIcon:
  307.             (**globH).useLargeIcon = !(**globH).useLargeIcon;
  308.             // request to be asked our dimensions again
  309.             result = (1L<<sdevResizeDisplay);
  310.             break;
  311.         case kDragFiles:
  312.             (**globH).acceptFiles = !(**globH).acceptFiles;
  313.             itemMark = (**globH).acceptFiles ? sdevMenuItemMark : noMark;
  314.             SetItemMark(menuH, kDragFiles, itemMark);
  315.             break;
  316.         
  317.         case kDragTextClippings:
  318.             (**globH).acceptText = !(**globH).acceptText;
  319.             itemMark = (**globH).acceptText ? sdevMenuItemMark : noMark;
  320.             SetItemMark(menuH, kDragTextClippings, itemMark);
  321.             break;
  322.         
  323.         case kSafeFinderQuit1: {
  324.             ProcessSerialNumber    finderPSN;
  325.             ProcessInfoRec        infoRec;
  326.  
  327.             infoRec.processInfoLength    =    sizeof(ProcessInfoRec);
  328.             infoRec.processName            =    nil;    //    no name wanted processName;
  329.             infoRec.processAppSpec        =    nil;    //    no spec wanted &procSpec;
  330.             
  331.             if (FindAProcess(kFinderType, kSysCreator, &finderPSN, &infoRec) == noErr)
  332.                 QuitProcess(finderPSN, (**globH).hasExtensionsStrip);
  333.             break;
  334.             }
  335.         
  336.         case kSafeFinderQuit2:
  337.             // request sdevInAppContext to be called once within Extensions Strip's context
  338.             result = (1L<<sdevQueueModule);
  339.             break;
  340.                         
  341.         case kCloseDown:
  342.             result = (1L<<sdevCloseNow);
  343.             break;
  344.     }                //end switch
  345.     
  346.     return(result);
  347. }
  348.  
  349. /******************************************************************************
  350.  sdevInit: allocate memory for our globals and init our globals
  351.  ******************************************************************************/
  352. long sdevInit(WindowRef statusPort)
  353. {
  354.     MyGlobalHandle    globH;
  355.     
  356.     //
  357.     // get some memory
  358.     //
  359.     globH = (MyGlobalHandle) NewHandleClear(sizeof(MyGlobals));
  360.     if (!globH)
  361.         goto exit;
  362.     
  363.     //
  364.     // temporarily lock our global handle because we pass pointers of it to toolbox
  365.     // functions.  If I wanted to be really cool I'd load all the handles into local
  366.     // variables to remove this need, as well as the repetitive double deferencing...
  367.     //
  368.     HLock((Handle)globH);
  369.  
  370.     //
  371.     // get our icon suite
  372.     //
  373.         if (SBGetDetachIconSuite(&(**globH).iconSuite, rIconSuiteId, svAllSmallData) != noErr) goto exit;
  374.     //
  375.     // get our string list
  376.     //
  377.         (**globH).myStrings = GetResource('STR#', rMyStringsID);
  378.         if (!(**globH).myStrings) goto exit;
  379.         DetachResource((**globH).myStrings);
  380.     //
  381.     // get our popup menu
  382.     //
  383.         (**globH).myMenuH = GetMenu(rPopupMenuID);
  384.         if (!(**globH).myMenuH) goto exit;
  385.         DetachResource((Handle)(**globH).myMenuH);
  386.     //
  387.     // get our arrow picture
  388.     //
  389.         (**globH).myArrowPict = GetPicture(rArrowPictID);
  390.         if (!(**globH).myArrowPict) goto exit;
  391.         DetachResource((Handle)(**globH).myArrowPict);
  392.     //
  393.     // setup our initial features
  394.     //
  395.         (**globH).currentFeatures = (
  396.                       (1L<<sdevWantMouseClicks)        // we handle mouse down
  397.                     | (1L<<sdevDontAutoTrack)        // we track the mouse, too
  398.                     | (1L<<sdevHasCustomHelp)        // custom help string
  399.                     | (1L<<sdevKeepModuleLocked)        // I need to be locked
  400.                                                     //         for drag-n-drop.
  401.                 );
  402.     //
  403.     // determine if Extensions Strip is running.
  404.     // If so, get my reference number and setup ES specific feature flags
  405.     //
  406.         (**globH).hasExtensionsStrip = HasExtensionsStrip();
  407.         if ((**globH).hasExtensionsStrip)
  408.         {
  409.             (**globH).myReferenceNum = SBGetMyReferenceNum();
  410.             (**globH).currentFeatures +=
  411.                 (
  412.                       (1L<<sdevHasDragHandlers)        // flag that we have drag handlers
  413.                     | (1L<<sdevDontPeriodicTickle)    // we don't need any idle time
  414.                     | (1L<<sdevInterceptAllEvents)    // get all events under Extensions Strip
  415.                 );
  416.         }
  417.     //
  418.     // setup the drag stuff
  419.     //
  420.         InstallDragHandlers(statusPort, globH);
  421.         (**globH).acceptFiles = true;
  422.         SetItemMark((**globH).myMenuH, kDragFiles, sdevMenuItemMark);
  423.     //
  424.     // set my handle free and return its value
  425.     //
  426.         HUnlock((Handle)globH);
  427.         return ((long) globH);
  428.     
  429.     //
  430.     // did not get any memory, don't install
  431.     //
  432. exit:
  433.     return (-1L);
  434. }
  435.  
  436. /******************************************************************************
  437.  sdevClose: free memory for our globals
  438.  ******************************************************************************/
  439. void sdevClose(MyGlobalHandle globH, WindowRef statusPort)
  440. {
  441. // useful macros:
  442. #define    myDisposeHandle(h)¥
  443.     if ((h) != nil)¥
  444.         DisposeHandle((Handle) (h))
  445. #define    myDisposeIconSuite(h, p1)¥
  446.     if ((h) != nil)¥
  447.         DisposeIconSuite(h, p1)
  448.  
  449. // dispose of everything:
  450.     if (globH){
  451.         myDisposeIconSuite((**globH).iconSuite, true);
  452.         myDisposeHandle((**globH).myMenuH);
  453.         myDisposeHandle((**globH).myStrings);
  454.         myDisposeHandle((**globH).myArrowPict);
  455.         
  456.         RemoveDragHandlers(statusPort, globH);
  457.         
  458.         DisposeHandle((Handle) globH);
  459.     }
  460. }
  461.  
  462. /******************************************************************************
  463.  sdevDraw: draw our icon and arrow pict
  464.  ******************************************************************************/
  465. void sdevDraw(MyGlobalHandle globH, Rect *statusRect, WindowRef statusPort)
  466. {
  467.     Rect        viewRect = *statusRect;
  468.     short        arrowHeight = 0;
  469.     PicHandle    myArrowPict = (**globH).myArrowPict;    // local copy to save deferencing
  470.     
  471.     //
  472.     // update the drag area (only required for Control/Desktop Strip)
  473.     //
  474.     viewRect.right -= kTriangleWidth;
  475.     (**globH).myBox = viewRect;
  476.     
  477.     //
  478.     // Draw our icon
  479.     //
  480.     DrawMyIcon(globH, false);
  481.     
  482.     //
  483.     // Draw our right-arrow pict to show that we have a popup menu
  484.     //
  485.     if (myArrowPict){
  486.         arrowHeight = height((*myArrowPict)->picFrame);
  487.         viewRect.left = viewRect.right;
  488.         viewRect.right += width((*myArrowPict)->picFrame);
  489.         viewRect.top += ((height(viewRect) - arrowHeight) >> 1);
  490.         viewRect.bottom = viewRect.top + arrowHeight;
  491.         DrawPicture(myArrowPict, &viewRect);
  492.     }
  493. }
  494.  
  495. #pragma mark -
  496.  
  497. /******************************************************************************
  498.  HasDragMgr: determine if the Drag Manager exists, and supports floaters
  499.  ******************************************************************************/
  500. Boolean    HasDragMgr(void)
  501. {
  502.     long    gestaltResponse;
  503.  
  504.     return(    (Gestalt(gestaltDragMgrAttr, &gestaltResponse) == noErr) &&
  505.             (gestaltResponse & (1L << gestaltDragMgrPresent)) &&
  506.             (gestaltResponse & (1L << gestaltDragMgrFloatingWind)) );
  507. }
  508.  
  509. /******************************************************************************
  510.  InstallDragHandlers: install & create everything having to do with drag handlers
  511.  ******************************************************************************/
  512. void InstallDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
  513. {
  514.     // local copies
  515.     DragTrackingHandlerUPP    myTrackingUPP;
  516.     DragReceiveHandlerUPP    myReceiveUPP;
  517.     
  518.     if (HasDragMgr()) {
  519.         myTrackingUPP = NewDragTrackingHandlerProc(MyTrackingHandler);
  520.         myReceiveUPP = NewDragReceiveHandlerProc(MyReceiveDropHandler);
  521.         
  522.         if (myTrackingUPP && myReceiveUPP) {    // got UPPs successfully
  523.             InstallTrackingHandler(myTrackingUPP, statusPort, (void*) globH);
  524.             InstallReceiveHandler(myReceiveUPP, statusPort, (void*) globH);
  525.         }
  526.         
  527.         (**globH).myTrackingUPP = myTrackingUPP;
  528.         (**globH).myReceiveUPP = myReceiveUPP;
  529.     } else {
  530.         // disable the drag-related menu items
  531.         // (doesn't move memory)
  532.         DisableItem((**globH).myMenuH, kUseDragNDrop);
  533.         DisableItem((**globH).myMenuH, kDragFiles);
  534.         DisableItem((**globH).myMenuH, kDragTextClippings);
  535.     }
  536. }
  537.  
  538. /******************************************************************************
  539.  RemoveDragHandlers: remove & dispose everything having to do with drag handlers
  540.  ******************************************************************************/
  541. void RemoveDragHandlers(WindowRef statusPort, MyGlobalHandle globH)
  542. {
  543.     // local copies
  544.     DragTrackingHandlerUPP    myTrackingUPP = (**globH).myTrackingUPP;
  545.     DragReceiveHandlerUPP    myReceiveUPP = (**globH).myReceiveUPP;
  546.     
  547.     if (myTrackingUPP) {
  548.         RemoveTrackingHandler(myTrackingUPP, statusPort);
  549.         DisposeRoutineDescriptor(myTrackingUPP);
  550.         (**globH).myTrackingUPP = 0L;
  551.     }
  552.     
  553.     if (myReceiveUPP) {
  554.         RemoveReceiveHandler(myReceiveUPP, statusPort);
  555.         DisposeRoutineDescriptor(myReceiveUPP);
  556.         (**globH).myReceiveUPP = 0L;
  557.     }
  558. }
  559.  
  560. /******************************************************************************
  561.  HasExtensionsStrip: determine if Extensions Strip is installed and running
  562.  ******************************************************************************/
  563. Boolean    HasExtensionsStrip(void)
  564. {
  565.     long    gestaltResponse;
  566.  
  567.     return(    (Gestalt(gestaltExtensionsStripAttr, &gestaltResponse) == noErr) &&
  568.             (gestaltResponse & (1L << gestaltExtensionsStripExists)) );
  569. }
  570.  
  571. #pragma mark -
  572.  
  573. /******************************************************************************
  574.  FindAProcess: run through the process list looking for the indicated program
  575.  ******************************************************************************/
  576. OSErr FindAProcess(OSType typeToFind, OSType creatorToFind,
  577.                              ProcessSerialNumberPtr processSN,
  578.                              ProcessInfoRecPtr infoRecToFill)
  579. {
  580.     OSErr    myErr    =    noErr;
  581.  
  582.     processSN->lowLongOfPSN        =    kNoProcess;
  583.     processSN->highLongOfPSN    =    0;
  584.     do
  585.     {
  586.         myErr    =    GetNextProcess(processSN);
  587.         if (myErr == noErr)
  588.             GetProcessInformation(processSN, infoRecToFill);
  589.     }
  590.     while ( (myErr == noErr) && ((infoRecToFill->processSignature != creatorToFind) ||
  591.                                  (infoRecToFill->processType != typeToFind)) );
  592.     return(myErr);
  593. }
  594.  
  595. /******************************************************************************
  596.  QuitProcess: Send a quit event to the specified process.  If you are using the
  597.                program Extensions Strip the event will be sent safely from within
  598.                its Apple Event aware context.
  599.  ******************************************************************************/
  600. void QuitProcess (ProcessSerialNumber PSN, Boolean hasExtensionsStrip)
  601. {    AEAddressDesc    applicationAddress;
  602.     AppleEvent        theEvent, returnEvent;
  603.     OSErr            err;
  604.  
  605.     AECreateDesc(typeProcessSerialNumber, &PSN, sizeof(ProcessSerialNumber), &applicationAddress);
  606.     AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &applicationAddress,
  607.                         kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
  608.     AEDisposeDesc(&applicationAddress);
  609.     if (hasExtensionsStrip) {
  610.         err = SBSimpleAESend(&theEvent);
  611.     } else {
  612.         err = AESend(&theEvent, &returnEvent,
  613.                     kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
  614.                     kAENormalPriority,
  615.                     kAEDefaultTimeout, nil, nil);
  616.         AEDisposeDesc(&returnEvent);
  617.     }
  618.     if (err) {
  619.         // error handling goes here
  620.         SysBeep(0);
  621.     }
  622.     AEDisposeDesc(&theEvent);
  623. }
  624.  
  625. /******************************************************************************
  626.  MouseInMyBounds: mouse is over my total clickable area
  627.  ******************************************************************************/
  628.  static Boolean MouseInMyBounds(MyGlobalHandle globH, WindowRef win,
  629.                                                      DragReference theDrag)
  630.  {
  631.     Boolean        result = false;
  632.     Point        theMouse;
  633.     Rect        hotBounds;
  634.     
  635.     if (GetDragMouse(theDrag, &theMouse, 0L) == noErr) {
  636.         GlobalToLocal(&theMouse);
  637.         if ((**globH).hasExtensionsStrip)
  638.             SBGetTotalModuleBounds(&hotBounds, win, (**globH).myReferenceNum);
  639.         else
  640.             hotBounds = (**globH).myBox;
  641.         
  642.         result = PtInRect(theMouse, &hotBounds);
  643.     }
  644.     
  645.     return(result);
  646.  }
  647.  
  648. void DrawMyIcon(MyGlobalHandle globH, Boolean selected)
  649. {
  650.     Rect        viewRect;
  651.     
  652.     if ((**globH).iconSuite)
  653.     {
  654.         // Get our icon's area
  655.         if ((**globH).hasExtensionsStrip) {
  656.             SBGetModuleBounds(&viewRect, (**globH).myReferenceNum);
  657.             viewRect.right -= kTriangleWidth;
  658.         } else
  659.             viewRect = (**globH).myBox;
  660.         
  661.         // Draw our icon
  662.         PlotIconSuite(&viewRect, atNone, selected ? ttSelected : ttNone,
  663.                       (**globH).iconSuite);
  664.     }
  665. }
  666. /******************************************************************************
  667.  MyTrackingHandler
  668.  ******************************************************************************/
  669. pascal OSErr MyTrackingHandler(short message, WindowRef win, void *handlerRefCon,
  670.                                                         DragReference theDrag)
  671. {
  672.     MyGlobalHandle    globH = (MyGlobalHandle) handlerRefCon;
  673.     ItemReference    theItem;
  674.     FlavorType        theType;
  675.     unsigned short    count, index, numFlavors, i;
  676.     
  677.     switch (message)
  678.     {
  679.         case dragTrackingEnterHandler:
  680.             // do special global initialization here
  681.             break;
  682.         
  683.         case dragTrackingEnterWindow:
  684.             // determine if we can support at least one of the drag items
  685.             (**globH).canAcceptDrag = false;        // default to rejection
  686.             if (CountDragItems(theDrag, &count) == noErr)
  687.             {
  688.                 for (index = 1; index <= count; index++)    // check all the items
  689.                 {
  690.                     if ((GetDragItemReferenceNumber(theDrag, index, &theItem) == noErr) &&
  691.                      (CountDragItemFlavors(theDrag, theItem, &numFlavors) == noErr)) {
  692.                         
  693.                         for (i = 1; i <= numFlavors; i++)    //    check all the flavors
  694.                         {
  695.                             if ((GetFlavorType(theDrag, theItem, i, &theType) == noErr) &&
  696.                                 (((**globH).acceptFiles ? (theType == flavorTypeHFS) : 0) ||
  697.                                 ((**globH).acceptText ? (theType == 'TEXT') : 0)))
  698.                             {
  699.                                 (**globH).canAcceptDrag = true;    // I like this flavor
  700.                             }
  701.                         }
  702.                     }
  703.                 }
  704.             }
  705.             break;
  706.         
  707.         case dragTrackingInWindow:
  708.             // check if the mouse is over me
  709.             if ((**globH).canAcceptDrag)
  710.                 if ((**globH).hasEntered != MouseInMyBounds(globH, win, theDrag))
  711.                 {
  712.                     (**globH).hasEntered = !(**globH).hasEntered;
  713.                     DrawMyIcon(globH, (**globH).hasEntered);
  714.                 }
  715.             break;
  716.         
  717.         case dragTrackingLeaveWindow:
  718.             // if dragTrackingInWindow didn't handle the mouse leaving our area, do it here.
  719.             if ((**globH).hasEntered)
  720.             {
  721.                 (**globH).hasEntered = false;
  722.                 DrawMyIcon(globH, false);
  723.             }
  724.             break;
  725.         
  726.         case dragTrackingLeaveHandler:
  727.             break;
  728.     }
  729.     
  730.     return((**globH).canAcceptDrag ? noErr : dragNotAcceptedErr);
  731. }
  732.  
  733. /******************************************************************************
  734.  MyReceiveDropHandler
  735.  ******************************************************************************/
  736. pascal OSErr MyReceiveDropHandler(WindowRef win, void *handlerRefCon,
  737.                                                 DragReference theDrag)
  738. {
  739.     MyGlobalHandle    globH    = (MyGlobalHandle) handlerRefCon;
  740.     OSErr            result    = dragNotAcceptedErr;    // default to cancel (do zoom-back animation)
  741.     
  742.     if ((**globH).hasEntered)
  743.     {
  744.         
  745.         //
  746.         // process the drag here:
  747.         //
  748.         SysBeep(0);
  749.         
  750.         //
  751.         
  752.         result = noErr;        // accept the drag (no zoom-back animation)
  753.     }
  754.     
  755.     return(result);
  756. }
  757.